package com.qf.common.redis.utils;

import com.qf.common.core.utils.ApplicationUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;

/**
 * 布隆过滤器的工具类
 */
@Slf4j
public class BloomUtils {

    private static StringRedisTemplate stringRedisTemplate;

    static {
        stringRedisTemplate = ApplicationUtils.getBean(StringRedisTemplate.class);
    }

    /*
    初始化的lua脚本

    --获取参数
    local bloomKey = KEYS[1]
    local error = ARGV[1]
    local max = ARGV[2]
    --执行redis命令初始化bloom过滤器  bf.reserve xxxx xxx xxxxx
    local result = redis.call('bf.reserve', bloomKey, error, max)
    return result
     */
    public static String initLua = "local bloomKey = KEYS[1]\n" +
            "local error = ARGV[1]\n" +
            "local max = ARGV[2]\n" +
            "local result = redis.call('bf.reserve', bloomKey, error, max)\n" +
            "return result";

    /*
    给布隆过滤器添加元素的脚本

    --获取参数
    local bloomKey = KEYS[1]
    local value = ARGV[1]
    return redis.call('bf.add', bloomKey, value)
     */
    public static String addLua = "local bloomKey = KEYS[1]\n" +
            "local value = ARGV[1]\n" +
            "return redis.call('bf.add', bloomKey, value)";

    /*
    判断是否存在

    local bloomKey = KEYS[1]
    local value = ARGV[1]
    return redis.call('bf.exists', bloomKey, value)
     */
    public static String existsLua = "local bloomKey = KEYS[1]\n" +
            "local value = ARGV[1]\n" +
            "return redis.call('bf.exists', bloomKey, value)";



    /**
     * 初始化bloom过滤器
     * @param bloomKey
     * @param error
     * @param maxValue
     * @return
     */
    public static boolean initBloom(String bloomKey, double error, Long maxValue){
        try {
            String result = stringRedisTemplate.execute(new DefaultRedisScript<>(initLua, String.class),
                    Collections.singletonList(bloomKey),
                    error + "", maxValue + "");
            log.debug("[init-bloom] - 初始化bloom过滤器 - {}", result);
        } catch (Throwable e){
            return false;
        }
        return true;
    }

    /**
     * 添加bloom过滤器的值
     * @return
     */
    public static boolean addBloom(String bloomKey, String value){
        Long result = stringRedisTemplate.execute(new DefaultRedisScript<Long>(addLua, Long.class),
                Collections.singletonList(bloomKey),
                value + "");
        log.debug("[add-bloom] - 给bloom过滤器添加元素 - {}", result);
        return result == 1;
    }

    /**
     * 是否存在，可能存在返回true，一定不存在返回false
     * @return
     */
    public static boolean isExists(String bloomKey, String value){
        Long result = stringRedisTemplate.execute(new DefaultRedisScript<Long>(existsLua, Long.class),
                Collections.singletonList(bloomKey),
                value + "");
        log.debug("[add-bloom] - 给bloom过滤器添加元素 - {}", result);
        return result == 1;
    }
}
